package com.tjp.subject.domain.service.impl;

import com.alibaba.fastjson.JSON;
import com.tjp.subject.common.entity.PageResult;
import com.tjp.subject.domain.convert.SubjectInfoConverter;
import com.tjp.subject.domain.entity.SubjectInfoBO;
import com.tjp.subject.domain.entity.SubjectOptionBO;
import com.tjp.subject.domain.handler.subject.SubjectTypeHandler;
import com.tjp.subject.domain.handler.subject.SubjectTypeHandlerFactory;
import com.tjp.subject.domain.service.SubjectInfoDomainService;
import com.tjp.subject.infra.basic.entity.SubjectCategory;
import com.tjp.subject.infra.basic.entity.SubjectInfo;
import com.tjp.subject.infra.basic.entity.SubjectLabel;
import com.tjp.subject.infra.basic.entity.SubjectMapping;
import com.tjp.subject.infra.basic.service.SubjectCategoryService;
import com.tjp.subject.infra.basic.service.SubjectInfoService;
import com.tjp.subject.infra.basic.service.SubjectLabelService;
import com.tjp.subject.infra.basic.service.SubjectMappingService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @program: jz-club
 * @description: 题目信息领域层接口实现类
 * @author: aaronTang
 * @create: 2024-02-29
 */
@Service
@Slf4j
public class SubjectInfoDomainServiceImpl implements SubjectInfoDomainService {

    @Resource
    private SubjectInfoService subjectInfoService;

    @Resource
    private SubjectMappingService subjectMappingService;

    @Resource
    private SubjectCategoryService subjectCategoryService;

    @Resource
    private SubjectLabelService subjectLabelService;

    @Resource
    private SubjectTypeHandlerFactory subjectTypeHandlerFactory;



    @Override
    public void insert(SubjectInfoBO subjectInfoBO) {

        if (log.isInfoEnabled()) {
            log.info("SubjectInfoDomainServiceImpl.insert.subjectInfoBO is {}", JSON.toJSONString(subjectInfoBO));
        }
        //使用策略模式+工厂模式进行题目分发,避免很多if-else代码
        SubjectInfo subjectInfo = SubjectInfoConverter.INSTANCE.subjectInfoConvertBOToEntity(subjectInfoBO);

        SubjectInfo insert = subjectInfoService.insert(subjectInfo);

        //通过工厂直接进行分发处理
        SubjectTypeHandler handler = subjectTypeHandlerFactory.getHandlerType(subjectInfo.getSubjectType());
        handler.add(subjectInfoBO);

        //获取所有分类id
        List<Long> categoryIds = subjectInfoBO.getCategoryIds();
        //获取所有标签id
        List<Long> labelIds = subjectInfoBO.getLabelIds();

        //完善分类标签关联表 多对多关系
        List<SubjectMapping> mappingList = new LinkedList<>();
        categoryIds.forEach(categoryId -> {
            labelIds.forEach(labelId -> {
                SubjectMapping subjectMapping = new SubjectMapping();
                //题目id
                subjectMapping.setSubjectId(subjectInfo.getId());
                //分类id
                subjectMapping.setCategoryId(categoryId);
                //标签id
                subjectMapping.setLabelId(labelId);
            });
        });

        subjectMappingService.batchInsert(mappingList);
    }

    @Override
    public PageResult<SubjectInfoBO> getSubjectPage(SubjectInfoBO subjectInfoBO) {
        if (log.isInfoEnabled()) {
            log.info("SubjectInfoDomainServiceImpl.getSubjectPage.subjectInfoBO is {}", JSON.toJSONString(subjectInfoBO));
        }

        PageResult<SubjectInfoBO> boPageResult = new PageResult<>();
        boPageResult.setPage(subjectInfoBO.getPage());
        boPageResult.setPageSize(subjectInfoBO.getPageSize());

        SubjectInfo subjectInfo = SubjectInfoConverter.INSTANCE.subjectInfoConvertBOToEntity(subjectInfoBO);

        int start = (subjectInfoBO.getPage() - 1) * subjectInfoBO.getPageSize();
        int count = subjectInfoService.countByCondition(subjectInfo,
                subjectInfoBO.getCategoryId(), subjectInfoBO.getLabelId());

        if (count == 0) {
            return boPageResult;
        }

        List<SubjectInfo> subjectInfoList = subjectInfoService.queryPage(subjectInfo,
                subjectInfoBO.getCategoryId(), subjectInfoBO.getLabelId(), start, subjectInfoBO.getPageSize());

        List<SubjectInfoBO> subjectInfoBOS = SubjectInfoConverter.INSTANCE.convertListInfoToBO(subjectInfoList);

        boPageResult.setRecords(subjectInfoBOS);
        boPageResult.setTotal(count);
        return boPageResult;
    }

    @Override
    public SubjectInfoBO querySubjectInfo(SubjectInfoBO subjectInfoBO) {
        SubjectInfo subjectInfo = subjectInfoService.queryById(subjectInfoBO.getId());

        //通过工厂分发策略去实现不同题目详情的查询
        SubjectTypeHandler handler = subjectTypeHandlerFactory.getHandlerType(subjectInfo.getSubjectType());

        //答案BO
        SubjectOptionBO optionBO = handler.query(subjectInfo.getId());

        //转化为吐给前端的BO
        SubjectInfoBO resultBO = SubjectInfoConverter.INSTANCE.convertOptionBOAndSubjecInfoToInfoBO(optionBO, subjectInfo);


        //根据题目id通过关系表反查出标签id,获取标签名称
        List<SubjectMapping> mappingList = subjectMappingService.queryBySubjectId(resultBO.getId());
        List<Long> labelIdList = mappingList.stream().map(SubjectMapping::getLabelId).collect(Collectors.toList());

        //查询出对应的标签
        List<SubjectLabel> subjectLabelList = subjectLabelService.batchQueryById(labelIdList);
        List<String> labelNameList = subjectLabelList.stream().map(SubjectLabel::getLabelName).collect(Collectors.toList());
        resultBO.setLabelName(labelNameList);
        if (log.isInfoEnabled()) {
            log.info("SubjectInfoDomainServiceImpl.querySubjectInfo.labelNameList is {}", JSON.toJSONString(labelNameList));
        }

        //查询出对应的分类
        List<Long> categoryIdList = mappingList.stream().map(SubjectMapping::getCategoryId).collect(Collectors.toList());
        List<SubjectCategory> categoryList = subjectCategoryService.batchQueryByCategoryId(categoryIdList);
        List<String> categoryNameList = categoryList.stream().map(SubjectCategory::getCategoryName).collect(Collectors.toList());
        resultBO.setCategoryName(categoryNameList);
        if (log.isInfoEnabled()) {
            log.info("SubjectInfoDomainServiceImpl.querySubjectInfo.categoryNameList is {}", JSON.toJSONString(categoryNameList));
        }

        return resultBO;
    }
}
